package com.base.test.mysql2es.service;

import com.base.test.mysql2es.model.Config;
import com.base.test.mysql2es.model.IncrementStorageType;
import com.base.test.mysql2es.model.Relation;
import com.google.common.collect.Maps;
import com.base.test.mysql2es.repository.DataRepository;
import com.base.test.mysql2es.util.DateUtil;
import com.base.test.mysql2es.util.FileUtil;
import com.base.test.mysql2es.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@Slf4j
@Component
@RequiredArgsConstructor
public class SyncDateService {

    @Value("${db2es.enable:true}")
    private boolean enable;

    private final Config config;
    private final DataRepository dataRepository;

    public void handle() {
        if (!enable) {
            return;
        }

        IncrementStorageType incrementType = config.getIncrementType();
        boolean deleteEveryTime = (incrementType == IncrementStorageType.TEMP_FILE) && config.isDeleteTempEveryTime();

        long start = System.currentTimeMillis();
        Map<String, Future<Long>> resultMap = Maps.newHashMap();
        for (Relation relation : config.getRelation()) {
            if (deleteEveryTime) {
                FileUtil.delete(relation.getTable(), relation.getIndex());
            }
            resultMap.put(relation.useKey(), dataRepository.asyncData(incrementType, relation));
        }
        for (Map.Entry<String, Future<Long>> entry : resultMap.entrySet()) {
            try {
                Long count = entry.getValue().get();
                if (ObjectUtil.isNotBlank(count)) {
                    if (log.isInfoEnabled()) {
                        long ms = System.currentTimeMillis() - start;
                        String tps = (count > 0 && ms > 0) ? String.valueOf(count * 1000 / ms) : "0";
                        log.info("同步({}) 条数({}), 用时({}), tps({})", entry.getKey(), count, DateUtil.toHuman(ms), tps);
                    }
                }
            } catch (InterruptedException | ExecutionException e) {
                if (log.isErrorEnabled()) {
                    log.error(String.format("同步 %s 线程异常, 用时(%s)",
                            entry, DateUtil.toHuman(System.currentTimeMillis() - start)), e);
                }
            } catch (Exception e) {
                if (log.isErrorEnabled()) {
                    log.error(String.format("同步 %s 异常, 用时(%s)",
                            entry, DateUtil.toHuman(System.currentTimeMillis() - start)), e);
                }
            }
        }
    }

    public void compensateHandle() {
        if (!enable) {
            return;
        }

        long start = System.currentTimeMillis();
        IncrementStorageType incrementType = config.getIncrementType();
        Map<String, Future<Long>> resultMap = Maps.newHashMap();
        for (Relation relation : config.getRelation()) {
            resultMap.put(relation.useKey(), dataRepository.compensateAsyncData(incrementType, relation));
        }
        for (Map.Entry<String, Future<Long>> entry : resultMap.entrySet()) {
            try {
                Long count = entry.getValue().get();
                if (ObjectUtil.isNotBlank(count)) {
                    if (log.isInfoEnabled()) {
                        long ms = System.currentTimeMillis() - start;
                        String tps = (count > 0 && ms > 0) ? String.valueOf(count * 1000 / ms) : "0";
                        log.info("补偿 => 同步({}) 条数({}), 用时({}), tps({})",
                                entry.getKey(), count, DateUtil.toHuman(ms), tps);
                    }
                }
            } catch (InterruptedException | ExecutionException e) {
                if (log.isErrorEnabled()) {
                    log.error(String.format("补偿 => 同步 %s 线程异常, 用时(%s)",
                            entry.getKey(), DateUtil.toHuman(System.currentTimeMillis() - start)), e);
                }
            } catch (Exception e) {
                if (log.isErrorEnabled()) {
                    log.error(String.format("补偿 => 同步 %s 异常, 用时(%s)",
                            entry.getKey(), DateUtil.toHuman(System.currentTimeMillis() - start)), e);
                }
            }
        }
    }
}
